#include "Geometry_wrap.h"
#include "Geometry/UGGeometryManager.h"
#include "Geometry/UGGeoLine.h"

#ifdef __cplusplus  
extern "C" { 
#endif

RWRAP_API char* RWRAP_CALL GeometryType2Name(UGint nType)
{
	UGC::UGGeometry::Type eType = (UGC::UGGeometry::Type)nType;
	switch (eType)
	{
	case UGC::UGGeometry::GeoPoint:
		return CopyStr("Point");
	case UGC::UGGeometry::GeoLine:
		return CopyStr("Line");
	case UGC::UGGeometry::GeoRegion:
		return CopyStr("Region");
	case UGC::UGGeometry::GeoText:
		return CopyStr("Text");
	default:
		return CopyStr("Null");
	}
}

RWRAP_API UGint RWRAP_CALL  Name2GeometryType(const char* name)
{
	UGString strName;
	strName.FromUTF8(name, strlen(name));
	if(strName.CompareNoCase(_U("Point")) == 0){
		return UGC::UGGeometry::GeoPoint;
	}
	if(strName.CompareNoCase(_U("Line")) == 0){
		return UGC::UGGeometry::GeoLine;
	}
	if(strName.CompareNoCase(_U("Region")) == 0){
		return UGC::UGGeometry::GeoRegion;
	}
	if(strName.CompareNoCase(_U("Text")) == 0){
		return UGC::UGGeometry::GeoText;
	}
	return UGC::UGGeometry::Null;
}

RWRAP_API UGGeometry* RWRAP_CALL Geometry_wrap_create(const char* type)
{
	UGint nType = Name2GeometryType(type);
	return UGGeometryManager::CreateGeometry(nType);
}

RWRAP_API UGint RWRAP_CALL Geometry_wrap_getID(const UGGeometry* pGeometry)
{
	if(pGeometry != NULL)
		return pGeometry->GetID();
	else 
		return 0;
}

RWRAP_API void RWRAP_CALL Geometry_wrap_setID(UGGeometry* pGeometry, UGint id)
{
	if(pGeometry != NULL && id > 0 )
	{
		pGeometry->SetID(id);
	}
}

RWRAP_API char* RWRAP_CALL Geometry_wrap_getType_name(const UGGeometry* pGeometry)
{
	if(pGeometry != NULL)
	{
		UGint nType = pGeometry->GetType();
		return GeometryType2Name(nType);
	}
	else 
	{
		return CopyStr("Null");
	}
}

RWRAP_API UGint RWRAP_CALL Geometry_wrap_getType(const UGGeometry* pGeometry)
{
	if(pGeometry != NULL)
	{
		UGint nType = pGeometry->GetType();
		return nType;
	}
	else 
	{
		return 0;
	}
}

RWRAP_API UGdouble RWRAP_CALL Geometry_wrap_getLength(const UGGeometry* pGeometry)
{
	if(pGeometry != NULL)
	{
		return pGeometry->GetLength();
	}
	else
	{
		return 0;
	}
}

RWRAP_API UGbool RWRAP_CALL Geometry_wrap_getInnerPoint(const UGGeometry* pGeometry, double& x, double& y)
{
	if(pGeometry != NULL)
	{
		UGPoint2D pnt = pGeometry->GetInnerPoint();
		x = pnt.x;
		y = pnt.y;
		return TRUE;
	}
	return FALSE;
}

RWRAP_API void RWRAP_CALL GeoPoint_wrap_make(UGGeoPoint* pGeometry, double x, double y)
{
	if(pGeometry != NULL)
	{
		pGeometry->SetX(x);
		pGeometry->SetY(y);
	}
}

RWRAP_API void RWRAP_CALL Geometry_wrap_make(UGGeometry* pGeometry, const UGdouble* px, const UGdouble* py, const UGint* pp, UGint nCount)
{
	if(pGeometry != NULL && nCount > 0)
	{
		UGint nPntCount = 0;
		for(UGint i=0; i<nCount; i++)
		{
			nPntCount += pp[i];
		}

		
		UGPoint2D* pPoints = new UGPoint2D[nPntCount];
		for(UGint i=0; i<nPntCount; i++)
		{
			pPoints[i] = UGPoint2D(px[i], py[i]);
		}

		pGeometry->Make(pPoints, pp, nCount);	
		
		delete[] pPoints;
		pPoints = NULL;
	}
}

RWRAP_API UGbool RWRAP_CALL Geometry_wrap_getPoints(UGGeometry* pGeometry, UGdouble*px, UGdouble*py)
{
	if(pGeometry != NULL)
	{
		UGAutoPtr<UGPoint2D> apPoints;
		UGAutoPtr<UGint> apPolyCount;
		UGint nSubCount = 0;
		if(!pGeometry->GetSpatialData(apPoints, apPolyCount, nSubCount))
		{
			return FALSE;
		}
		UGPoint2D* pPoints = (UGPoint2D*) apPoints.GetData();
		UGint* pPolyCount = (UGint*) apPolyCount.GetData();
		UGint nIndex = 0;
		for(UGint i=0; i<nSubCount; i++)
		{
			for(UGint j=0; j<pPolyCount[i]; j++)
			{
				px[nIndex] = pPoints[j].x;
				py[nIndex] = pPoints[j].y;
				nIndex ++;
			}
			pPoints += pPolyCount[i];
		}
		return TRUE;
	}
	return FALSE;
}


RWRAP_API UGint RWRAP_CALL Geometry_wrap_getSubCount(UGGeometry* pGeometry)
{
	if(pGeometry != NULL)
		return pGeometry->GetSubCount();
	else
		return 0;
}
RWRAP_API UGbool RWRAP_CALL Geometry_wrap_getPolyCount(UGGeometry* pGeometry, UGint* pPolyCount)
{
	if(pGeometry != NULL)
	{
		for(UGint i=0; i<pGeometry->GetSubCount(); i++)
		{
			pPolyCount[i] = pGeometry->GetSubPntCount(i);
		}
		return TRUE;
	}
	return FALSE;
}

RWRAP_API UGint RWRAP_CALL Geometry_wrap_getDimension(UGGeometry* pGeometry)
{
	if(pGeometry != NULL)
	{
		return pGeometry->GetDimension();
	}
	return -1;
}

RWRAP_API UGbool RWRAP_CALL Geometry_wrap_getBounds(UGGeometry* pGeometry, UGdouble rect[])
{
	if(pGeometry != NULL)
	{
		const UGRect2D& rc = pGeometry->GetBounds();
		rect[0] = rc.left;
		rect[1] = rc.top;
		rect[2] = rc.right;
		rect[3] = rc.bottom;
		return TRUE;
	}
	return FALSE;
}

RWRAP_API UGdouble RWRAP_CALL Geometry_wrap_getArea(UGGeometry* pGeometry)
{
	if(pGeometry != NULL)
	{
		return pGeometry->GetArea();
	}
	return 0.0;
}

RWRAP_API void RWRAP_CALL GeoRegion_wrap_holes(UGGeoRegion* pGeometry, UGint* p)
{
	if(pGeometry != NULL)
	{
		pGeometry->CheckPolygon(pGeometry->GetPoints(), pGeometry->GetPolyCounts(), pGeometry->GetSubCount(), p);
	}
}

RWRAP_API void RWRAP_CALL GeoRegion_warp_protected_decompose(UGGeoRegion*pGeometry, Wrap_Geometrys& result)
{
	if(pGeometry != NULL)
	{
		UGArray<UGGeoRegion*> arySub;
		if(pGeometry->ProtectedDecomposeEx(arySub) && arySub.GetSize() > 0)
		{
			result.nCount = arySub.GetSize();
			result.pGeos = new UGGeometry*[arySub.GetSize()];
			for(UGint i=0; i<arySub.GetSize(); i++)
			{
				result.pGeos[i] = arySub[i];
			}
		}
	}
}

RWRAP_API void RWRAP_CALL Geometry_wrap_delete(UGGeometry* pGeometry)
{
	delete pGeometry;
}
RWRAP_API void RWRAP_CALL GeoPoint_wrap_detete(UGGeoPoint* pGeometry)
{
	delete pGeometry;
}
RWRAP_API void RWRAP_CALL GeoLine_wrap_delete(UGGeoLine* pGeometry)
{
	delete pGeometry;
}
RWRAP_API void RWRAP_CALL GeoRegion_wrap_delete(UGGeoRegion* pGeometry)
{
	delete pGeometry;
}

#ifdef __cplusplus
}
#endif